package cn.lyjuan.payment.third.base.pay.chl.impl.weixin.util;

import cn.lyjuan.base.util.StringUtils;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.ResultEntity;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.TransfersDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.*;

@Slf4j
public class WxUtils {

    /**
     * 参数名字典排序生成XML
     *
     * @param params
     * @return
     */
    public static String sortParamXml(Map<String, String> params) {
        // 1. 根据参数名字典排序
        List<String> keyList = Arrays.asList(params.keySet().toArray(new String[params.size()]));
        Collections.sort(keyList);

        // 2. 拼接签名参数
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (String k : keyList) {
            if (StringUtils.isNull(params.get(k)))
                continue;// 空值不签名

            sb.append("<").append(k).append("><![CDATA[")
                    .append(null == params.get(k) ? "" : params.get(k))
                    .append("]]></").append(k).append(">");
        }

        sb.append("</xml>");

        return sb.toString();
    }

    /**
     * 判断是否是微信环境
     *
     * @param userAgent
     * @return
     */
    public static boolean isWxEnvir(String userAgent) {
        log.info("判断微信支付环境：userAgent >> " + userAgent);

        if (StringUtils.isNull(userAgent)) return false;// 用户代理信息为空

        if (userAgent.indexOf("MicroMessenger") < 0) return false;// 不是微信浏览器

//		if (!StringUtil.isDouble(userAgent)) return false;// 最后分组信息不是 Double
//		
//		if (Double.parseDouble(userAgent.trim()) < 5) return false;// 版本号小于 5.0

        // 是微信支付环境
        return true;
    }

    /**
     * 为签名排序请求参数
     *
     * @param params params
     * @return String
     */
    public static String sortParamForSign(Map<String, String> params) {
        if (StringUtils.isNull(params)) {
            return "";
        }
        ;
        // 参数字典升序排序
        Map<String, String> sortedMap = new TreeMap<String, String>();
        sortedMap.putAll(params);
        // 参数Form表单方式拼接
        StringJoiner sj = new StringJoiner("&");
        for (Iterator<Map.Entry<String, String>> it = sortedMap.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, String> e = it.next();
            String key = e.getKey();
            String value = e.getValue();
            if (StringUtils.isNull(key)) {
                // 跳过无效参数
                continue;
            }
            if (StringUtils.isNull(value)
                    || "null".equalsIgnoreCase(value)) {
                // 跳过空值参数
                continue;
            }
            if ("sign".equalsIgnoreCase(e.getKey())) {
                // 跳过签名参数
                continue;
            }
            sj.add(key + "=" + value);
        }
        return sj.toString();
    }

    /**
     * 签名
     *
     * @param appKey appKey
     * @param params params
     * @return String
     */
    public static String sign(String appKey, Map<String, String> params) {
        if (StringUtils.isNull(params)) {
            return "";
        }
        String paramStr = WxUtils.createLinkString(appKey, params);
        String mysign = paramStr + "&key=" + appKey;
        return DigestUtils.md5Hex(mysign).toUpperCase();
    }

    /**
     * @param model 微信接口请求参数DTO对象
     * @return ResultEntity 返回结构体
     */
    public static ResultEntity doTransfers(String url, String certPath, TransfersDto model, Integer systemErrorRetryTimes) {
        try {
            // 2.封装请求参数
            StringBuilder reqXmlStr = new StringBuilder();
            reqXmlStr.append("<xml>");
            reqXmlStr.append("<mchid>" + model.getMchid() + "</mchid>");
            reqXmlStr.append("<mch_appid>" + model.getMch_appid() + "</mch_appid>");
            reqXmlStr.append("<device_info>" + model.getDevice_info() + "</device_info>");
            reqXmlStr.append("<nonce_str>" + model.getNonce_str() + "</nonce_str>");
            reqXmlStr.append("<check_name>" + model.getCheck_name() + "</check_name>");
            reqXmlStr.append("<re_user_name>" + model.getRe_user_name() + "</re_user_name>");
            reqXmlStr.append("<openid>" + model.getOpenid() + "</openid>");
            reqXmlStr.append("<amount>" + model.getAmount() + "</amount>");
            reqXmlStr.append("<desc>" + model.getDesc() + "</desc>");
            reqXmlStr.append("<sign>" + model.getSign() + "</sign>");
            reqXmlStr.append("<partner_trade_no>" + model.getPartner_trade_no() + "</partner_trade_no>");
            reqXmlStr.append("<spbill_create_ip>" + model.getSpbill_create_ip() + "</spbill_create_ip>");
            reqXmlStr.append("</xml>");
            // 3.加载证书请求接口
            String result = HttpRequestHandler.httpsRequest(url, reqXmlStr.toString(), model, certPath, systemErrorRetryTimes);
            boolean tag = checkWxXmlResSuccess(result) && checkXmlResLabelContainsFlag(result, "result_code", "CDATA[SUCCESS]");
            return new ResultEntity(tag, result);
        } catch (Exception e) {
            log.error("wx transfer error: [{}]", e);
            return new ResultEntity(false, e.getMessage());
        }
    }

    /**
     * 检查微信xml请求结果
     *
     * @param res res
     * @return boolean
     */
    public static boolean checkWxXmlResSuccess(String res) {
        return checkXmlResLabelContainsFlag(res, "return_code", "CDATA[SUCCESS]");
    }

    /**
     * 检查微信xml请求结果-SystemError
     *
     * @param res res
     * @return boolean
     */
    public static boolean checkWxXmlResSystemError(String res) {
        return checkXmlResLabelContainsFlag(res, "return_code", "CDATA[SYSTEMERROR]");
    }

    /**
     * 检查xml的字符串中指定标签中是否有flag
     *
     * @param res   res
     * @param label label
     * @param flag  flag
     * @return boolean
     */
    public static boolean checkXmlResLabelContainsFlag(String res, String label, String flag) {
        if (res == null) {
            return false;
        }
        int tag1 = res.indexOf(label);
        if (tag1 == -1) {
            return false;
        }
        int tag2 = res.indexOf(label, tag1 + 1);
        if (tag2 == -1) {
            return false;
        }
        return res.substring(tag1, tag2).contains(flag);
    }

    public static String createLinkString(String appKey, Map<String, String> paramMap) {
        // 微信签名规则 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=4_3
        List<String> keys = new ArrayList<>(paramMap.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = paramMap.get(key);
            if (value == null || value.equals("")) {
                continue;
            }
            prestr += key + "=" + value + "&";
        }
        // 拼接时，不包括最后一个&字符
        prestr = prestr.substring(0, prestr.length() - 1);
        return prestr;
    }

    public static String getNonce_str() {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 15; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}













